# !/usr/bin/env python3
# -*- coding: utf-8 -*-

'此模块负责收集文件信息并形成原始数据结构'

from lxml import etree
import fs

from error import MatchingError
from ref import SourceReference


class LateralRoot(object):
    """处理文件路径

    负责获取并返回文件路径

    Attributes:
        __data_path: map对象，包含文件路径的字符串
    """

    def __init__(self) -> None:
        """类初始化"""
        self.__data_path = self.__absorb()

    def __absorb(self) -> map:
        """获取文件引用

        获取本目录下xml及jpg文件路径

        Args:
            None

        Returns:
            返回一个map，包含对本地xml文件以及jpg文件位置的引用

            如：
            {
                'xml_path': '/config.xml',
                'jpg_paths': ['/imgs/a.jpg', '/imgs/b.jpg']
            }

        Raises:
            None
        """
        osfs = fs.open_fs('./')

        output = {
            'xml_path': None,
            'jpg_paths': []
        }
        for p in osfs.walk.files(filter=['*.xml', '*.jpg'], exclude=['category.xml']): # noqa E501
            if 'xml' in p:
                output['xml_path'] = p
            else:
                output['jpg_paths'].append(p)
        return output

    @property
    def data_path(self) -> map:
        """对外只读属性接口"""
        return self.__data_path


class AxialRoot(object):
    """形成原始数据

    解析成规定map形式的原始数据

    Attributes:
        file_path: map对象，包含文件路径
        __data_origin: map对象，解析的数据
    """

    def __init__(self, file_path) -> None:
        """类初始化"""
        self.__data_origin = self.__decompose(file_path)

    def __decompose(self, file_path) -> map:
        """xml解析

        解析xml文件为map结构数据

        Args:
            file_path: xml文件位置的引用

        Returns:
            一个包含一下键值的的map:
                dates——问题发生时间
                units——单位工程代号
                issues——问题内容
                sources——问题的来源，现场检查、全球眼或专项检查
                traceables——是否可以追踪

        Raises:
            MatchingError: 匹配错误，当有相同属性值的date标签重复；或当traceable值为true的数量与图片数量不一致
        """
        output = {
            'dates': [],
            'units': [],
            'issues': [],
            'sources': [],
            'traceables': []
        }

        parser = etree.XMLParser(remove_blank_text=True)
        tree = etree.parse('.{}'.format(file_path['xml_path']), parser)

        output['issues'] = tree.xpath('//issue/text()')

        if len(tree.xpath('//date/@value')) != len(set(tree.xpath('//date/@value'))): # noqa E501
            raise MatchingError('有相同日期的date标签')

        for v in tree.xpath('//issue'):
            output['dates'] += v.xpath('./ancestor::date/@value')
            output['units'] += v.xpath('./parent::individual/@unit')

        for v in tree.xpath('//@source'):
            if v:
                output['sources'].append(SourceReference['{}'.format(v)].value)
            else:
                output['sources'].append(SourceReference['x'].value)

        if len(tree.xpath('//issue[@traceable="true"]')) != len(file_path['jpg_paths']): # noqa E501
            raise MatchingError('traceable数量与图片数量不一致')

        for v in tree.xpath('//@traceable'):
            if 't' in v:
                output['traceables'].append(fs.path.basename(file_path['jpg_paths'].pop(0))) # noqa E501
            else:
                output['traceables'].append('/')
        return output

    @property
    def data_origin(self) -> map:
        """对外只读属性接口"""
        return self.__data_origin


if __name__ == '__main__':
    lateral_root = LateralRoot()
    print(lateral_root.data_path)
